import { createHash } from "crypto";
import {
  commands,
  Event,
  EventEmitter,
  ExtensionContext,
  FileDecoration,
  FileDecorationProvider,
  FileRenameEvent,
  ProviderResult,
  TreeItem,
  Uri,
  window,
  workspace,
} from "vscode";

class NoteFileDecoration extends FileDecoration {
  key: string;
  constructor(key: string, label: string, tooltip?: string) {
    super(label, tooltip);
    this.key = key;
  }
}
const D: typeof FileDecoration & { validate?: () => void } = FileDecoration;
D.validate = () => {};

export class FileNameNotesDecorationProvider implements FileDecorationProvider {
  private notes: Record<string, string>;
  private context: ExtensionContext;
  private _onDidChangeFileDecorations: EventEmitter<Uri | Uri[] | undefined> =
    new EventEmitter<Uri | Uri[]>();
  readonly onDidChangeFileDecorations: Event<Uri | Uri[] | undefined> =
    this._onDidChangeFileDecorations.event;
  private disposables: { dispose(): void }[] = [];
  
  private maxLength: number;

  constructor(context: ExtensionContext) {
    this.context = context;
    this.notes = context.globalState.get("tree-item-notes") || {};
    this.maxLength = workspace.getConfiguration('treeItemNotes').get('maxLength') || 20;
    
    // 监听文件重命名事件
    this.disposables.push(
      workspace.onDidRenameFiles(this.handleFileRename.bind(this))
    );

    // 监听配置变化
    this.disposables.push(
      workspace.onDidChangeConfiguration(e => {
        if (e.affectsConfiguration('treeItemNotes.maxLength')) {
          this.maxLength = workspace.getConfiguration('treeItemNotes').get('maxLength') || 20;
          this.refresh();
        }
      })
    );
  }
  
  private handleFileRename(event: FileRenameEvent) {
    event.files.forEach(({ oldUri, newUri }) => {
      const oldKey = this.generateUriHashKey(oldUri);
      const newKey = this.generateUriHashKey(newUri);
      
      if (oldKey && this.notes[oldKey]) {
        // 迁移备注到新键
        this.notes[newKey] = this.notes[oldKey];
        delete this.notes[oldKey];
        this.context.globalState.update("tree-item-notes", this.notes);
        
        // 刷新新旧URI的装饰
        this.refresh(oldUri);
        this.refresh(newUri);
      }
    });
  }
  refresh(uri?: Uri) {
    this._onDidChangeFileDecorations.fire(uri);
  }
  update(key: string, note: string) {
    this.notes[key] = note;
    this.context.globalState.update("tree-item-notes", this.notes);
  }
  provideFileDecoration(uri: Uri): ProviderResult<NoteFileDecoration> {
    const key = this.generateUriHashKey(uri);
    if (key && this.notes[key]) {
      const note = this.notes[key];
      const displayNote = note.length > this.maxLength 
        ? `${note.substring(0, this.maxLength)}...` 
        : note;
      return new NoteFileDecoration(key, displayNote, note);
    }
  }
  async set(obj: any) {
    const uri = this.getUri(obj);
    if (!uri) {
      window.showErrorMessage("当前对象无法设置备注");
      return;
    }
    const key = this.generateUriHashKey(uri);
    const currentNote = key ? this.notes[key] : '';
    const input = await window.showInputBox({
      placeHolder: "输入备注内容",
      prompt: "备注内容",
      value: currentNote
    });
    if (input === undefined) {
      return;
    }
    this.update(this.generateUriHashKey(uri), input || '');
    this.refresh(uri);
  }
  async remove(obj: any) {
    const uri = this.getUri(obj);
    if (!uri) {
      window.showErrorMessage("当前对象没有设置备注");
      return;
    }
    const selection = await window.showInformationMessage(
      "确定要删除该备注吗？",
      "确定",
      "取消"
    );

    if (selection !== "确定") {
      return;
    }
    const key = this.generateUriHashKey(uri);
    if (key) {
      delete this.notes[key];
      this.context.globalState.update("tree-item-notes", this.notes);
      this.refresh(uri);
    }
  }
  async clear(obj: any) {
    const selection = await window.showInformationMessage(
      "确定要清空所有备注吗？此操作不可逆！",
      "确定",
      "取消"
    );

    if (selection !== "确定") {
      return;
    }
    this.notes = {};
    this.context.globalState.update("tree-item-notes", this.notes);
    this.refresh();
  }
  getUri(obj: any) {
    if (obj instanceof Uri) {
      return obj;
    } else if (obj instanceof TreeItem && obj.resourceUri) {
      return obj.resourceUri;
    }
    return;
  }
  generateUriHashKey(uri: Uri) {
    return createHash("md5").update(uri.toString()).digest("hex");
  }

  static init(context: ExtensionContext) {
    const provider = new FileNameNotesDecorationProvider(context);
    context.subscriptions.push(
      window.registerFileDecorationProvider(provider),
      commands.registerCommand("tree-item-notes.set", (obj: any) =>
        provider.set(obj)
      ),
      commands.registerCommand("tree-item-notes.remove", (obj: any) =>
        provider.remove(obj)
      ),
      commands.registerCommand("tree-item-notes.clear", (obj: any) =>
        provider.clear(obj)
      ),
      ...provider.disposables
    );
  }
}
